#include "RWTools.h"

#include <GCPnts_AbscissaPoint.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <Standard_Handle.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Ellipse.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <BRepTools.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Edge.hxx>
#include <BRepAlgoAPI_Section.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <BRepBndLib.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>

bool ContainsActor(const std::vector<Handle(QIVtkSelectionPipeline)>& actorCollection, const Handle(QIVtkSelectionPipeline)& actorToFind)
{
	// 遍历查找
	for (auto actor : actorCollection)
	{
		if (actor == actorToFind)
		{
			return true; // 找到了
		}
	}
	return false; // 未找到
}

void RemoveActor(std::vector<Handle(QIVtkSelectionPipeline)>& actorCollection, const Handle(QIVtkSelectionPipeline)& actorToRemove)
{
	actorCollection.erase(std::remove(actorCollection.begin(), actorCollection.end(), actorToRemove), actorCollection.end());
}

int GetIndexFromActor(const std::vector<Handle(QIVtkSelectionPipeline)>& actorCollection, const Handle(QIVtkSelectionPipeline)& actorToFind)
{
	for (size_t i = 0; i < actorCollection.size(); i++)
	{
		if (actorCollection[i] == actorToFind)
		{
			return i;
		}
	}
	return -1; // 未找到
}

Handle(QIVtkSelectionPipeline) GetActorFromIndex(const std::vector<Handle(QIVtkSelectionPipeline)>& actorCollection, int index)
{
	if (index >= 0 && index < actorCollection.size())
	{
		return actorCollection[index];
	}
	return nullptr;
}

bool ContainsVertex(const std::vector<gp_Pnt>& points, const gp_Pnt& point, const Standard_Real theLinearTolerance /*= Precision::Confusion()*/)
{
	if (points.size() == 0)
	{
		return false;
	}

	return std::find_if(points.begin(), points.end(), [&point, &theLinearTolerance](const gp_Pnt& item)
		{
			return item.IsEqual(point, theLinearTolerance);
		}) != points.end();
}

bool ContainsVertex(gp_Pnt& findPoint, const std::vector<gp_Pnt>& points, const gp_Pnt& point, const Standard_Real theLinearTolerance /*= Precision::Confusion()*/)
{
	if (points.size() == 0)
	{
		return false;
	}

	std::vector<gp_Pnt>::const_iterator findItem = std::find_if(points.begin(), points.end(), [&point, &theLinearTolerance](const gp_Pnt& item)
		{
			return item.IsEqual(point, theLinearTolerance);
		});

	if (findItem != points.end())
	{
		findPoint = *findItem;
		return true;
	}
	return false;
}

std::vector<gp_Pnt> getDividedPointsOnEdge(const TopoDS_Edge& edge, int divisions)
{
	std::vector<gp_Pnt> newPoints;

	// 参数检查
	if (divisions < 1) return newPoints;

	// 获取曲线和参数范围
	Standard_Real firstParam, lastParam;
	Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, firstParam, lastParam);
	if (curve.IsNull()) return newPoints;

	// 创建曲线适配器
	GeomAdaptor_Curve adaptorCurve(curve);
	// 计算总弧长（使用适配器）
	const Standard_Real tolerance = Precision::Confusion();
	Standard_Real totalLength = GCPnts_AbscissaPoint::Length(
		adaptorCurve,
		firstParam,
		lastParam,
		tolerance
	);
	if (totalLength <= tolerance) return newPoints;

	const Standard_Real segmentLength = totalLength / divisions;

	for (int i = 0; i <= divisions; ++i) 
	{
		Standard_Real param;
		const Standard_Real s = i * segmentLength;

		if (i == 0) 
		{
			param = firstParam;
		}
		else if (i == divisions) 
		{
			param = lastParam;
		}
		else 
		{
			GCPnts_AbscissaPoint abscissa(
				adaptorCurve, // 使用适配器
				s,
				firstParam,
				tolerance
			);
			if (!abscissa.IsDone()) continue;
			param = abscissa.Parameter();
		}

		gp_Pnt p;
		curve->D0(param, p);
		newPoints.push_back(p);
	}

	return newPoints;
}

bool GetArcCenter(const TopoDS_Edge& edge, gp_Pnt& center)
{
	// 获取曲线和参数范围
	Standard_Real firstParam, lastParam;
	Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, firstParam, lastParam);

	if (curve.IsNull()) 
	{
		return false; // 无效曲线
	}

	// 直接处理完整圆
	Handle(Geom_Circle) circle = Handle(Geom_Circle)::DownCast(curve);
	if (!circle.IsNull()) 
	{
		center = circle->Position().Location();
		return true;
	}

	// 处理修剪后的圆弧
	Handle(Geom_TrimmedCurve) trimmedCurve = Handle(Geom_TrimmedCurve)::DownCast(curve);
	if (!trimmedCurve.IsNull()) 
	{
		Handle(Geom_Curve) baseCurve = trimmedCurve->BasisCurve();
		Handle(Geom_Circle) baseCircle = Handle(Geom_Circle)::DownCast(baseCurve);
		if (!baseCircle.IsNull()) 
		{
			center = baseCircle->Position().Location();
			return true;
		}
	}

	return false; // 非圆弧边
}

bool GetEllipseCenter(const TopoDS_Edge& edge, gp_Pnt& center)
{
	// 获取曲线和参数范围
	Standard_Real firstParam, lastParam;
	Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, firstParam, lastParam);

	if (curve.IsNull()) 
	{
		return false; // 无效曲线
	}

	// 直接处理完整椭圆
	Handle(Geom_Ellipse) ellipse = Handle(Geom_Ellipse)::DownCast(curve);
	if (!ellipse.IsNull()) 
	{
		center = ellipse->Position().Location(); // 椭圆中心
		return true;
	}

	// 处理修剪后的椭圆弧
	Handle(Geom_TrimmedCurve) trimmedCurve = Handle(Geom_TrimmedCurve)::DownCast(curve);
	if (!trimmedCurve.IsNull()) 
	{
		// 获取基曲线
		Handle(Geom_Curve) baseCurve = trimmedCurve->BasisCurve();

		// 检查基曲线是否是椭圆
		Handle(Geom_Ellipse) baseEllipse = Handle(Geom_Ellipse)::DownCast(baseCurve);
		if (!baseEllipse.IsNull()) 
		{
			center = baseEllipse->Position().Location();
			return true;
		}
	}

	return false; // 非椭圆边
}

bool GetFaceParametricCenter(const TopoDS_Face& face, gp_Pnt& center)
{
	if (face.IsNull())
	{
		return false;
	}

	// 获取面的几何表面
	Handle(Geom_Surface) surface = BRep_Tool::Surface(face);

	// 获取面的参数范围
	Standard_Real uMin, uMax, vMin, vMax;
	BRepTools::UVBounds(face, uMin, uMax, vMin, vMax);

	// 计算参数中点
	Standard_Real uMid = (uMin + uMax) / 2.0;
	Standard_Real vMid = (vMin + vMax) / 2.0;

	// 在参数中点处求点
	surface->D0(uMid, vMid, center);

	return true;
}

std::vector<gp_Pnt> GetEdgeIntersections(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2, double tolerance)
{
	std::vector<gp_Pnt> intersections;

	// 创建截面计算工具
	BRepAlgoAPI_Section sectionTool(edge1, edge2, tolerance);
	sectionTool.Build();

	if (sectionTool.IsDone()) 
	{
		// 获取结果形状（可能是顶点或边）
		const TopoDS_Shape& result = sectionTool.Shape();

		// 提取所有顶点
		TopExp_Explorer explorer(result, TopAbs_VERTEX);
		for (; explorer.More(); explorer.Next()) 
		{
			const TopoDS_Vertex& vertex = TopoDS::Vertex(explorer.Current());
			intersections.push_back(BRep_Tool::Pnt(vertex));
		}
	}

	return intersections;
}

bool IsBoundingBoxesIntersect(const TopoDS_Shape& shape1, const TopoDS_Shape& shape2)
{
    if (shape1.IsNull() || shape2.IsNull())
    {
        return false;
    }

	Bnd_Box bbox_1, bbox_2;
	BRepBndLib::AddOptimal(shape1, bbox_1);
	BRepBndLib::AddOptimal(shape2, bbox_2);

	return !bbox_1.IsOut(bbox_2);
}

bool IsPointOnEdge(const gp_Pnt& thePoint, const TopoDS_Edge& theEdge, const double tolerance)
{
	// 处理退化边（如线段退化为顶点）
	if (BRep_Tool::Degenerated(theEdge)) {
		TopExp_Explorer exp(theEdge, TopAbs_VERTEX);
		for (; exp.More(); exp.Next()) {
			const TopoDS_Vertex& v = TopoDS::Vertex(exp.Current());
			gp_Pnt pv = BRep_Tool::Pnt(v);
			if (thePoint.Distance(pv) <= tolerance) {
				return true;
			}
		}
		return false;
	}

	// 获取边的几何曲线及其参数范围
	double first, last;
	Handle(Geom_Curve) curve = BRep_Tool::Curve(theEdge, first, last);
	if (curve.IsNull()) {
		return false; // 无效曲线
	}

	// 创建曲线适配器，限制在边的参数范围内
	GeomAdaptor_Curve adaptorCurve(curve, first, last);

	// 计算点到曲线的极值（最近点）
	Extrema_ExtPC extrema;
	extrema.Initialize(adaptorCurve, first, last); // 限制参数范围
	extrema.Perform(thePoint);

	if (!extrema.IsDone() || extrema.NbExt() == 0) {
		return false; // 极值计算失败或无解
	}

	// 找到所有极值点中的最小平方距离
	const double tolSq = tolerance * tolerance;
	double minSqDist = extrema.SquareDistance(1);
	for (int i = 2; i <= extrema.NbExt(); ++i) {
		const double sqDist = extrema.SquareDistance(i);
		if (sqDist < minSqDist) {
			minSqDist = sqDist;
		}
	}

	return (minSqDist <= tolSq);
}

bool GetEdgeEndPoints(const TopoDS_Edge& theEdge, gp_Pnt& p1, gp_Pnt& p2, double tolerance)
{
	if (BRep_Tool::Degenerated(theEdge)) {
		return false; // 退化边，返回空
	}

	TopoDS_Vertex V1, V2;
	TopExp::Vertices(theEdge, V1, V2);

	bool hasV1 = !V1.IsNull();
	bool hasV2 = !V2.IsNull();

	if (hasV1 && hasV2) {
		gp_Pnt pos1 = BRep_Tool::Pnt(V1);
		gp_Pnt pos2 = BRep_Tool::Pnt(V2);
		if (pos1.Distance(pos2) <= tolerance) {
			return false;
		}
		else {
			p1 = pos1;
			p2 = pos2;
			return true;
		}
	}
	else {
		double first, last;
		Handle(Geom_Curve) curve = BRep_Tool::Curve(theEdge, first, last);
		if (curve.IsNull()) {
			return false; // 无效的曲线
		}

		gp_Pnt firstPoint = curve->Value(first);
		gp_Pnt lastPoint = curve->Value(last);

		if (firstPoint.Distance(lastPoint) <= tolerance) {
			return false; // 首尾位置闭合，认为是闭合边
		}
		else {
			// 如果没有闭合，返回首尾参数点
			p1 = firstPoint;
			p2 = lastPoint;
			return true;
		}
	}
}

double DistancePointToEdgeGeometric(const gp_Pnt& point, const TopoDS_Edge& edge)
{
	// 提取边的几何曲线及其参数范围
	Standard_Real uFirst, uLast;
	Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, uFirst, uLast);

	// 投影点到曲线
	GeomAPI_ProjectPointOnCurve projector(point, curve);
	if (projector.NbPoints() < 1) 
	{
		std::cout << "Failed to project point to curve." << std::endl;
		return -1;
	}

	// 返回最近距离
	return projector.LowerDistance();
}

gp_Vec GetEdgeDirection(const TopoDS_Edge& edge)
{
	// 获取边的曲线和参数范围
	Standard_Real first, last;
	Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, first, last);

	// 选择曲线中点作为计算导数的点
	Standard_Real midParam = (first + last) / 2.0;

	// 计算该点的导数，即方向向量
	gp_Pnt point;
	gp_Vec tangentVec;
	curve->D1(midParam, point, tangentVec);

	// 返回方向向量
	return tangentVec.Normalized();
}

bool operator==(const gp_XYZ& lhs, const gp_XYZ& rhs)
{
	return IsNearlyEqual(lhs.X(), rhs.X()) && IsNearlyEqual(lhs.Y(), rhs.Y()) && IsNearlyEqual(lhs.Z(), rhs.Z());
}

bool operator!=(const gp_XYZ& lhs, const gp_XYZ& rhs)
{
	return !(lhs == rhs);
}

bool operator==(const gp_Pnt& lhs, const gp_Pnt& rhs)
{
	return lhs.XYZ() == rhs.XYZ();
}

bool operator!=(const gp_Pnt& lhs, const gp_Pnt& rhs)
{
	return !(lhs == rhs);
}

bool operator==(const gp_Dir& lhs, const gp_Dir& rhs)
{
	return lhs.XYZ() == rhs.XYZ();
}

bool operator!=(const gp_Dir& lhs, const gp_Dir& rhs)
{
	return !(lhs == rhs);
}

bool operator==(const gp_Ax1& lhs, const gp_Ax1& rhs)
{
	return lhs.Direction() == rhs.Direction() && lhs.Location() == rhs.Location();
}

bool operator!=(const gp_Ax1& lhs, const gp_Ax1& rhs)
{
	return !(lhs == rhs);
}

bool operator==(const gp_Ax2& lhs, const gp_Ax2& rhs)
{
	return lhs.Axis() == rhs.Axis() && lhs.XDirection() == rhs.XDirection() && lhs.YDirection() == rhs.YDirection();
}

bool operator!=(const gp_Ax2& lhs, const gp_Ax2& rhs)
{
	return !(lhs == rhs);
}

gp_Pnt operator+(const gp_Pnt& p1, const gp_Pnt& p2)
{
	return gp_Pnt(
		p1.X() + p2.X(),
		p1.Y() + p2.Y(),
		p1.Z() + p2.Z()
	);
}

gp_Pnt operator-(const gp_Pnt& p1, const gp_Pnt& p2)
{
	return gp_Pnt(
		p1.X() - p2.X(),
		p1.Y() - p2.Y(),
		p1.Z() - p2.Z()
	);
}

gp_Pnt operator*(const gp_Pnt& p, float n)
{
	return gp_Pnt(
		p.X() * n,
		p.Y() * n,
		p.Z() * n
	);
}


